//(function($) {

	empty = function(val) {
		return (typeof(val) === "undefined" || val===null || val===false || val===0 || val==='' || (jQuery.isArray(val) && val.length==0) || jQuery.isEmptyObject(val));
	};
	
	Matrix = function(matrix) {
		this.matrix = matrix;
		this._fix();
	};
	
	Matrix.prototype = {
		empty: 0,
		
		clone: function() {
			return new Matrix(JSON.decode(JSON.encode(this.matrix)));
		},
		
		width: function(idx) {
			return this.matrix[empty(idx) ? 0 : idx].length;
		},
		
		height: function() {
			return this.matrix.length;
		},
		
		_fix: function() {
			// process matrix
			var _max = 0;
			for(var r=0; r<this.height(); r++) {
				_max = Math.max(_max, this.width(r));
			}
			
			for(var r=0; r<this.height(); r++) {
				// Fill empty spaces. Make matrix rectangular.
				var _dif = _max - this.width(r);
				
				if(_dif>0)	console.info(this, "Expanding row "+r);
				
				for(var s=0; s<_dif; s++)
					this.matrix[r].push(this.empty);
			}
		},
		
		line: function(idx, isVLine) {
			if(empty(isVLine)) {
				return jQuery.extend([], this.matrix[idx]);				
			} else {
				var line = [];
				for(var r=0; r<this.height(); r++)
					line.push(this.matrix[r][idx]);
				return line;
			}
		},

		insertLine: function(idx, line, isVLine) {
			if(empty(isVLine)) {
				if(line.length != this.width()) console.warn("Matrix:", "Not valid line!");
				this.matrix.splice(idx, 0, line);
			} else {
				if(line.length != this.height()) console.warn("Matrix:", "Not valid line!");
				for(var r=0; r<this.height(); r++) {
					this.matrix[r].splice(idx, 0, line[r]);
				}
			}
		},
		
		removeLine: function(idx, isVLine) {
			if(empty(isVLine)) {
				this.matrix.splice(idx, 1);
			} else {
				for(var r=0; r<this.height(); r++) {
					this.matrix[r].splice(idx, 1);
				}
			}
		},
		
		rotate: function() {
			var _newMatrix = [];
			for(var c=0; c<this.width(); c++) {
				var _line = this.line(c, true);
				_line.reverse();
				_newMatrix.push(_line);
			}
			this.matrix = _newMatrix;
		}
	};
	

	MPLayoutElm = function(options) {
		jQuery.extend(this, {
			position: { left: 0, top: 0 },
			size: { width: 0, height: 0 },
			type: 0,
			isRound: false,
			isTable: false,
			scheme: [],
			title: "",
			sits: []
		});
		jQuery.extend(this, options);
		
		if(jQuery.isArray(this.scheme)) {
			this.scheme = new Matrix(this.scheme);
			this._validateScheme();
		}
	};
	
	MPLayoutElm.prototype = {
		placeSize: 54,
		table: 1,
		resizer: 2,
		empty: 0,
		nonplace: 3,
		
		serialize: function() {
			if(this.scheme instanceof Matrix)
				this.scheme = this.scheme.matrix;
			return JSON.decode(JSON.encode(this));
		},
		
		deserialize: function(obj) {
			return new MPLayoutElm(obj);
		},
		
		clone: function() {
			var _clone = this.serialize();
			return this.deserialize(_clone);
		},
		
		_validateScheme: function(){			
			// Duplicate resizers for rotations
			for(var r=0; r<this.scheme.height(); r++) {
				if(this.scheme.matrix[r][0] == this.resizer && this.scheme.matrix[r][this.scheme.width()-1]==0)
					this.scheme.matrix[r][this.scheme.width()-1] = this.resizer;
			}
			for(var c=0; c<this.scheme.width(); c++) {
				if(this.scheme.matrix[0][c] == this.resizer && this.scheme.matrix[this.scheme.height()-1][c]==0)
					this.scheme.matrix[this.scheme.height()-1][c] = this.resizer;
			}
		},
		
		_getTableResizers: function(isVert) {
			var _indexes = [];
			var _line = this.scheme.line(0, isVert);
			for(var i=0; i<_line.length; i++) {
				if(_line[i] == this.resizer)
					_indexes.push(i);
			}
			return _indexes;
		},
		
		_getMatrixPos: function(){
			var _placeHolders = [];
			var _tables = [];
			var _grid = this.scheme.matrix;
			
			for(var i=0; i<this.scheme.height(); i++) {
				for(var j=0; j<this.scheme.width(); j++) {
					if(_grid[i][j] == this.table) {
						_tables.push({y: i, x: j});
						continue;
					}
					else if(_grid[i][j] != this.nonplace) {
						if( typeof(_grid[i-1])!="undefined" && _grid[i-1][j] == this.table 
							|| typeof(_grid[i+1])!="undefined" && _grid[i+1][j] == this.table
							|| typeof(_grid[i][j-1])!="undefined" && _grid[i][j-1] == this.table
							|| typeof(_grid[i][j+1])!="undefined" && _grid[i][j+1] == this.table) {
							
							_placeHolders.push({y: i, x: j});
						}
					}
				}
			}
			return {tables: _tables, placeholders: _placeHolders};
		}, 
		
		getPlaceHolders: function() {
			return this._getMatrixPos().placeholders;
		},
		
		getTables: function() {
			return this._getMatrixPos().tables;
		},
		
		getTableBounds: function()  {
			var bounds = { left: 0, top: 0, width: 0, height: 0};
			var tables = this.getTables();
			
			var hor = [];
			var ver = [];
			
			for(var i=0; i<tables.length; i++) {
				ver.push(tables[i].y);
				hor.push(tables[i].x);
			}
			
			bounds.left = Math.min.apply(Math, hor);
			bounds.top = Math.min.apply(Math, ver);
			bounds.width = (Math.max.apply(Math, hor)+1) - bounds.left;
			bounds.height = (Math.max.apply(Math, ver)+1) - bounds.top;
			
			return bounds;
		},

		getTableBiggestArea: function()  {
			var area = {left:0, top:0, width:0, height:0};
			
			var lines = [];
			var pos = [];
			var max = 0;
			
			// Get table lines lengths
			for(var r=0; r<this.scheme.height(); r++) {
				lines.push([]);
				pos.push([]);
				var len = 0;
				for(var c=0; c<this.scheme.width(); c++) {
					if(this.scheme.matrix[r][c] == this.table) {
						len++;
					} else {
						max = Math.max(max, len);
						lines[lines.length-1].push(len);
						pos[pos.length-1].push(c);
						len = 0;
					}		
				}
				if(len>0) {
					max = Math.max(max, len);
					lines[lines.length-1].push(len);
					pos[pos.length-1].push(c);
				}
			}

			for(var r=0; r<lines.length; r++) {
				for(var l=0; l<lines[r].length; l++) {
					if(max == lines[r][l]) {
						area.left = pos[r][l]-lines[r][l];
						area.top = r;
						area.width = lines[r][l];
						area.height = 1;
						
						// Get sub area
						for(var n=r+1; n<lines.length; n++) {
							var includeSub = false;
							for(var k=0; k<lines[n].length; k++) {
								if(lines[n][k]>=area.width && pos[n][k]>=pos[r][l] && pos[n][k]-lines[n][k]<=area.left) {
									area.height++;
									includeSub = true;
								}			
							}
							if(!includeSub) break;
						}
						r = lines.length;
						break;
					}
				}
			}
			
			return area;
		},

		_resizeTableScheme: function(size, isVert) {
			var _line = this.scheme.line(0, isVert);

			if(_line.length != size) {
				var _indexes = [], _lastSizers = [];
				
				_indexes = this._getTableResizers(isVert);
				for(var i=0; i<_line.length; i++) {
					if(_line[i] < 0)
						_lastSizers.push(_line[i]);
				}
				
				var _minSizer = Math.min.apply(Math, jQuery.extend([-1], _lastSizers));
				var _offset = 0;
				if(_line.length > size && _lastSizers.length>0) {
					for(var i=0; i<_line.length; i++) {
						if(_line[i] == _minSizer) {
							this.scheme.removeLine(i+_offset, !isVert);
							_offset--;
						}
					}					
				} else if(_line.length < size) {
					for(var i=0; i<_indexes.length; i++) {
						var _lineCpy = this.scheme.line(_indexes[i]+_offset, !isVert);
						_lineCpy[0] = _lineCpy[_lineCpy.length-1] = _minSizer-1;							
						this.scheme.insertLine(_indexes[i]+1+_offset, _lineCpy, !isVert);
						_offset++;
					}
				}
			}
		},
		
		resizeScheme: function(size) {
			
			if(this.isRound && size>=2) {
				this.scheme = size;
			} else if(!this.isRound && this.isTable){
				this._resizeTableScheme(size.width, false);
				this._resizeTableScheme(size.height, true);
			}
		},
		
		rotateScheme: function() {
			this.scheme.rotate();
			
			for(var i=0; i<this.sits.length; i++){
				if(this.sits[i] != null) {
					var _position = { 
							y: this.sits[i].position.x,
							x: this.scheme.width()-1 - this.sits[i].position.y
						};
					
					this.sits[i].position.x = _position.x;
					this.sits[i].position.y = _position.y;
				}
			}
		}		
	};	
	
	MPLayout = function(options) {
		jQuery.extend(this, {viewMode: false, layoutMembers: [], pair: [], guests: []}); 
		
		jQuery.extend(this, options);
	
		this.stage
			.addClass("mp-canvas ui-widget")
			.data("mp-manager", this);
		
		this.toolbar
			.addClass("mp-toolbar ui-accordion ui-widget ui-helper-reset ui-accordion-icons")
			.data("mp-manager", this);

		this._fillToolBar();
		
		if(!this.viewMode) {
			this._bindToolbarEvents();
			
			jQuery( ".mp-draggable li" )
				.css("cursor", "move")
				.hover(function(event){ jQuery(this).addClass("ui-state-active"); }, function(event){ jQuery(this).removeClass("ui-state-active"); });
		}
	};
	
	MPLayout.prototype = {
		localization: {
			current: "ru-RU",
			"ru-RU": {
				STAGE_OBJECTS: "Объекты",
				GUESTS: "Гости",
				TITLE: "Заголовок",
				PLACE_COUNT: "Число мест",
				OK: "ОК",
				APPLY: "Применить",
				CANCEL: "Отмена",
				ACTION_EDIT: "Изменить",
				ACTION_DELETE: "Удалить", 
				ACTION_DELETE_CONFIRM: "Удалить?",
				ACTION_ROTATE: "Повернуть",
				ACTION_ENCREASE: "Увеличить",
				ACTION_ENCREASE_H: "Увеличить по горизонтали",
				ACTION_ENCREASE_V: "Увеличить по вертикали",
				ACTION_REDUCE: "Уменьшить",
				ACTION_REDUCE_H: "Уменьшить по горизонтали",
				ACTION_REDUCE_V: "Уменьшить по вертикали"
			}
		},
			
		// fill toolbar
		
		_: function(name) {
			return this.localization[this.localization.current][name];
		},
		
		_fillToolBar: function() {
			
			// Fill objects			
			this.toolbar
				.append("<h3><i class=\"ui-icon ui-icon-triangle-1-s\"></i><a href=\'#\'>"+this._('STAGE_OBJECTS')+"</a></h3>")
				.append("<div class=\'mp-draggable mp-objects\'><ul></ul></div>");
	
			var $ul = this.toolbar.find(".mp-objects ul");

			for(var i=0; i<this.layoutMembers.length; i++) {
				var layoutScheme = this.layoutMembers[i];
				jQuery("<li/>")
					.addClass("ui-state-default")
					.data("scheme", layoutScheme)
					.appendTo($ul)
					.text(layoutScheme.title);
			}
	
			// Fill guests
			this.toolbar
				.append("<h3><i class=\"ui-icon ui-icon-triangle-1-s\"></i><a href=\'#\'>"+this._('GUESTS')+"</a></h3>")
				.append("<div class=\'mp-draggable mp-droppable mp-guests\'><ul></ul></div>");
	
			var $ul = this.toolbar.find(".mp-guests ul");

			for(var i=0; i<2; i++) {
				jQuery("<li/>")
					.addClass("ui-state-default mp-pair mp-draggable-guest")
					.data("data", this.pair[i])
					.appendTo($ul)
					.append(jQuery("<span/>").append(jQuery("<p/>").text(this.pair[i].name)));
			}
			
			for(var i=0; i<this.guests.length; i++) {
				jQuery("<li/>")
					.addClass("ui-state-default mp-draggable-guest")
					.data("data", this.guests[i])
					.appendTo($ul)
					.append(jQuery("<span/>").append(jQuery("<p/>").text(this.guests[i].name)));
			}
			
			// Process custom accordion
			this.toolbar.find("h3")
				.click(function() {
					jQuery(this).next().toggle("blind");
					jQuery(this).find(".ui-icon").toggleClass("ui-icon-triangle-1-s ui-icon-triangle-1-e");
					return false;
				})
				.addClass("ui-accordion-header ui-helper-reset ui-state-default")
				.next().addClass("ui-helper-reset").show();
		},
		
		_sortGuests: function() {
			var $_guestlist = this.toolbar.find('.mp-guests ul');
			var $_listitems = $_guestlist.children('li').get();
			$_listitems.sort(function(a, b) {
			   var compA = jQuery(a).hasClass("mp-pair") ? 1 : 0;
			   var compB = jQuery(b).hasClass("mp-pair") ? 1 : 0;
			   return (compA > compB) ? -1 : (compA < compB) ? 1 : 0;
			});
			jQuery.each($_listitems, function(idx, itm) { $_guestlist.append(itm); });
		},
		
		_bindToolbarEvents: function(){
					
			jQuery( ".mp-draggable.mp-objects li" ).each(function(){
				jQuery(this).draggable({
					revert: "invalid",
					revertDuration: 0,
					cursor: "move",
					appendTo: "body",
					cursorAt: {left: 50, top: 50},
					zIndex: 10000,
					helper: function(event) {
						var $this = jQuery(this);
						return jQuery("<div/>").addClass("mp-obj-helper mp-obj-type"+$this.data("scheme").type).text(jQuery(this).text());							
					}
				});
			});
			
			this.stage.droppable({
				activeClass: "ui-custom-highlight",
				hoverClass: "ui-state-highlight",
				accept: ".mp-draggable.mp-objects li",
				drop: function( event, ui ) {
					jQuery(this).data("mp-manager")._appendObject(this, ui);
				}
			});		
	
			jQuery( ".mp-draggable.mp-guests li" ).each(function(){
				jQuery(this).draggable({
					revert: "invalid",
					revertDuration: 200,
					cursor: "move",
					appendTo: "body",
					cursorAt: {left: 10, top: 5},
					zIndex: 10000,
					helper: function(event) { return jQuery("<p/>").addClass("ui-state-default").text(jQuery(this).text()); }
				});
			});
			
			jQuery(".mp-droppable.mp-guests").droppable({
					activeClass: "ui-custom-highlight",
					hoverClass: "ui-state-highlight",
					accept: ".mp-draggable-guest",
					drop: function( event, ui ) {
						jQuery(".mp-toolbar").data("mp-manager")._revertGuest(this, ui);
					}
			});
		},
		
		serialize: function() {
			var data = [];
			var _manager = this; 
			this.stage.children(".mp-obj").each(function(){
				var _obj = _manager._serializeObject(jQuery(this));
				data.push(_obj);
			});
			return data;
		},

		_serializeObject: function($obj_container) {
			var data = {};
			
			data = $obj_container.data("scheme");			
			data.position = $obj_container.position();
			data.size = { width: $obj_container.width(), height: $obj_container.height() };
			data.sits = this._getTableSits($obj_container);
			
			data = data.serialize();
			
			return data;
		},		
		
		processObjects: function(objs) {
			for(var i=0; i<objs.length; i++)
				this._processObject(this.stage, objs[i]);
		},
		
		clearStage: function() {
			var _manager = this;
			this.stage.children(".mp-obj").each(function(){
				_manager._removeObject(jQuery(this));
			});
		},
	
		_appendObject: function(stage, ui) {
			var $canvas = jQuery(stage);
	
			var _layoutObj = ui.draggable.data("scheme").clone();
			_layoutObj.position.top = ui.offset.top - $canvas.offset().top + $canvas.scrollTop();
			_layoutObj.position.left = ui.offset.left - $canvas.offset().left + $canvas.scrollLeft();
			
			var data = _layoutObj.serialize();
			
			this._processObject(stage, data);
		},
		
		_processObject: function(stage, data) {
			var $canvas = jQuery(stage);			
			
			var _layoutObj = MPLayoutElm.prototype.deserialize(data);
			var _top = _layoutObj.position.top;
			var _left = _layoutObj.position.left;
			
			var $obj_container = jQuery("<div/>")
			.data("scheme", _layoutObj)
			.addClass("mp-obj mp-obj"+_layoutObj.type)
			.appendTo($canvas)
			.css("top", _top)
			.css("left", _left);
						
			this._renderObject($obj_container);
			this._processPlaceholders($obj_container);
			this._renderSits($obj_container);
			
			if(!this.viewMode) {
				this._addObjectActions($obj_container);
				this._bindObjectEvents($obj_container);
			}
		},
		
		_renderObject: function($obj_container) {
		
			var layoutObj = $obj_container.data("scheme");

			if(!empty(layoutObj.size) && !empty(layoutObj.size.width) && !empty(layoutObj.size.height)) {
				$obj_container
					.css("width", layoutObj.size.width)
					.css("height", layoutObj.size.height);
			} else if(layoutObj.scheme instanceof Matrix) {
				$obj_container
					.css("width", layoutObj.scheme.width() * layoutObj.placeSize)
					.css("height", layoutObj.scheme.height() * layoutObj.placeSize);
			}
			
			if(!layoutObj.isRound && layoutObj.isTable) {
		
				var $grid = jQuery("<table/>");
				var grid = [];
		
				$obj_container.append($grid);
			
				var grid_size = { height: layoutObj.scheme.height(), width: layoutObj.scheme.width()};
		
				for(var i=0; i<grid_size.height; i++) {
					var $tr = jQuery("<tr/>").appendTo($grid);
					grid.push([]);
					for(var j=0; j<grid_size.width; j++) {
						var $td = jQuery("<td/>").appendTo($tr);
						grid[i].push($td);
		
						if(layoutObj.scheme.matrix[i][j] == 1) {
							$td.css("cursor", "move");			
							$td.addClass("mp-table mp-handler");
						
							jQuery("<div/>")
								.css("width", layoutObj.placeSize)
								.css("height", layoutObj.placeSize)
								.appendTo($td);
						
							if(typeof(layoutObj.scheme.matrix[i-1])=="undefined" || layoutObj.scheme.matrix[i-1][j] != 1)
								$td.addClass("mp-border-top");
							if(typeof(layoutObj.scheme.matrix[i][j-1])=="undefined" || layoutObj.scheme.matrix[i][j-1] != 1)
								$td.addClass("mp-border-left");
							if(typeof(layoutObj.scheme.matrix[i+1])=="undefined" || layoutObj.scheme.matrix[i+1][j] != 1)
								$td.addClass("mp-border-bottom");
							if(typeof(layoutObj.scheme.matrix[i][j+1])=="undefined" || layoutObj.scheme.matrix[i][j+1] != 1)
								$td.addClass("mp-border-right");		 
						}
					}
				}
				
				
				var _placeholders = layoutObj.getPlaceHolders();
				for(var i=0; i<_placeholders.length; i++) {
					var _pos = _placeholders[i];
					var $place = jQuery("<div/>")
						.css("widht", layoutObj.placeSize)
						.css("height", layoutObj.placeSize)
						.appendTo(grid[_pos.y][_pos.x]);
					$place.data("position", {y: _pos.y, x: _pos.x});
					this._addPlaceHolder($obj_container, $place);
				}
							
				var bounds = this._getTableBounds($obj_container);
				
				$obj_container
					.css("width", bounds.width)
					.css("height", bounds.height);
				
				$grid.css("margin-left", -bounds.left)
					.css("margin-top", -bounds.top); 
	
			} else if(layoutObj.isRound && layoutObj.isTable) {
				$obj_container.addClass("mp-round");
				var $rtbl = jQuery("<div/>").addClass("mp-table mp-handler");
				
				$obj_container.append($rtbl);
				
				var horde = (layoutObj.placeSize + 4);
				var ang = 2*Math.PI / layoutObj.scheme;

				var size = horde/Math.sin(ang/2) - layoutObj.placeSize - 2;
				size = Math.max(layoutObj.placeSize*3/2, size);
	
				$rtbl.css("width", size).css("height", size);

				var r = (size+4 + layoutObj.placeSize+2)/2 + 2;
	
				var curAngle = 0;
				var position = 0;
				var count = layoutObj.scheme;
				do {
					var x = r*Math.cos(curAngle) - (layoutObj.placeSize+2)/2 + (size)/2;
					var y = r*Math.sin(curAngle) - (layoutObj.placeSize+2)/2 + (size)/2;
	
					var $place = jQuery("<div/>").appendTo($obj_container);	
					$place
						.data("position", position)
						.css("position", "absolute")
						.css("top", y)
						.css("left", x);
					this._addPlaceHolder($obj_container, $place);
					
					curAngle += ang;
					position++;
					count--;
				} while(count>0)	
					
				$obj_container
					.css("width", "auto")
					.css("height", "auto");
	
			} else if(!layoutObj.isRound && !layoutObj.isTable) {
				$obj_container.addClass("mp-stage mp-handler")
				.css("cursor", "move");
	
			} else {
				$obj_container.addClass("mp-stage mp-round mp-handler")
				.css("cursor", "move");
			};

		},

		_bindObjectEvents: function($obj_container) {
			var layoutObj = $obj_container.data("scheme");
			
			$obj_container
			.hover(function(event){ jQuery(this).find(".mp-obj-actions").show(); }, function(event){ jQuery(this).find(".mp-obj-actions").hide(); })
			.draggable({ 
				stack: ".mp-obj" , 
				handle: ".mp-handler",
				containment: this.stage,
				stop: function(event, ui) {
					jQuery(this).data("position", ui.position);
				}
			});
	
			if(!layoutObj.isTable) {
				$obj_container.resizable({
					minWidth: 10,//layoutObj.placeSize * layoutObj.scheme.width(),
					minHeight: 10//layoutObj.placeSize * layoutObj.scheme.height()
				});
			};
		},
		
		_processPlaceholders: function($obj_container) {
			var layoutObj = $obj_container.data("scheme");
			
			if(layoutObj.isTable && !layoutObj.isRound) {
				
				var grid = this._getTableGrid($obj_container); 
				$obj_container.find(".mp-place-holder").each(function(){
					var $this = jQuery(this);
					var pos = $this.data("position");
					if(typeof(grid[pos.y+1])!="undefined" && grid[pos.y+1][pos.x].hasClass("mp-table")) {
						$this.addClass("mp-table-down");
					} else if(typeof(grid[pos.y+1])!="undefined" && grid[pos.y+1][pos.x].find(".mp-place-holder").length) {
						$this.addClass("mp-placeholder-down");
					} else if(typeof(grid[pos.y+1])=="undefined" || !grid[pos.y+1][pos.x].find(".mp-place-holder").length) {
						$this.addClass("mp-empty-down");
					}
					
					if(typeof(grid[pos.y-1])!="undefined" && grid[pos.y-1][pos.x].hasClass("mp-table")) {
						$this.addClass("mp-table-up");					
					} else if(typeof(grid[pos.y-1])!="undefined" && grid[pos.y-1][pos.x].find(".mp-place-holder").length) {
						$this.addClass("mp-placeholder-up");
					} else if(typeof(grid[pos.y-1])=="undefined" || !grid[pos.y-1][pos.x].find(".mp-place-holder").length) {
						$this.addClass("mp-empty-up");
					}
					
					if(typeof(grid[pos.y][pos.x+1])!="undefined" && grid[pos.y][pos.x+1].hasClass("mp-table")) {
						$this.addClass("mp-table-right");					
					} else if(typeof(grid[pos.y][pos.x+1])!="undefined" && grid[pos.y][pos.x+1].find(".mp-place-holder").length) {
						$this.addClass("mp-placeholder-right");
					} else if(typeof(grid[pos.y][pos.x+1])=="undefined" || !grid[pos.y][pos.x+1].find(".mp-place-holder").length) {
						$this.addClass("mp-empty-right");
					}
					
					if(typeof(grid[pos.y][pos.x-1])!="undefined" && grid[pos.y][pos.x-1].hasClass("mp-table")) {
						$this.addClass("mp-table-left");					
					} else if(typeof(grid[pos.y][pos.x-1])!="undefined" && grid[pos.y][pos.x-1].find(".mp-place-holder").length) {
						$this.addClass("mp-placeholder-left");
					} else if(typeof(grid[pos.y][pos.x-1])=="undefined" || !grid[pos.y][pos.x-1].find(".mp-place-holder").length) {
						$this.addClass("mp-empty-left");
					}
				});
			} else if(layoutObj.isTable && layoutObj.isRound) {
				
				var count = layoutObj.scheme;
				var step = 360/count;
				var ang = 0;
				$obj_container.find(".mp-place-holder").each(function(){
					var $this = jQuery(this); 
					$this.css("vertical-align", "middle");
					var delta = 0;
					
					if(ang>=90 && ang<270) {
						$this.css("direction", "rtl");
						delta = 180;
					}
					
					if(count>5) {
						$this
							.css("-webkit-transform", "rotate("+(delta+ang)+"deg)")
							.css("-moz-transform", "rotate("+(delta+ang)+"deg)")
							.css("-o-transform", "rotate("+(delta+ang)+"deg)")
							.css("-ms-transform", "rotate("+(delta+ang)+"deg)");
					}
					ang += step;
				});
			}
		},
		
		_getTableGrid: function($obj_container) {
			var $grid = $obj_container.children("table");
			var grid = [];
			
			$grid.children("tbody").children().each(function(){
				grid.push([]);
				jQuery(this).children().each(function(){
					grid[grid.length-1].push(jQuery(this));
				});
				
			});
			
			return grid;
		},
		
		_getTableBounds: function($obj_container) {	
			
			if(!empty($obj_container.data("bounds")))
				return $obj_container.data("bounds");
				
			var bounds = $obj_container.data("scheme").getTableBounds();
			var cellWidth = $obj_container.find("table td").eq(0).width();
			var cellHeight = $obj_container.find("table td").eq(0).height();
						
			bounds.left *= cellWidth;
			bounds.top *= cellHeight;
			bounds.width *= cellWidth;
			bounds.height *= cellHeight;
			
			$obj_container.data("bounds", bounds);
			
			return bounds;
		},
		
		_getTableBiggestArea: function($obj_container) {			

			if(!empty($obj_container.data("area")))
				return $obj_container.data("area");

			var area = $obj_container.data("scheme").getTableBiggestArea();
			var cellWidth = $obj_container.find("table td").eq(0).width();
			var cellHeight = $obj_container.find("table td").eq(0).height();
			
			area.left *= cellWidth;
			area.top *= cellHeight;
			area.width *= cellWidth;
			area.height *= cellHeight;
			
			$obj_container.data("area", area);
			
			return area;
		},
		
		_addObjectActions: function($obj_container) {
			var layoutObj = $obj_container.data("scheme");
			
			var $area = $obj_container;
			
			if(layoutObj.isTable && !layoutObj.isRound) {
				var area =  this._getTableBiggestArea($obj_container);
				var bounds = this._getTableBounds($obj_container);
				
				$area = jQuery("<div/>").addClass("mp-obj-area mp-handler")
							.css("position", "absolute")
							.css("left", area.left-bounds.left)
							.css("top", area.top-bounds.top)
							.css("width", area.width)
							.css("height", area.height);
				
				$obj_container.append($area);			
			}
			
			var $title = jQuery("<span/>")
				.addClass("mp-obj-title")
				.text(layoutObj.title)
				.css("top", "50%")
				.css("width", "100%")
				.css("text-align", "center")
				.css("position", "absolute");
			
			if(layoutObj.isTable)
				$title.addClass("mp-handler");
			
			$area.append($title);
			
			$title
				.css("margin-top", -$title.height()/2);			

			var $actions_div = jQuery("<div/>").addClass("mp-obj-actions")
				.css("position", "absolute")
				.css("white-space", "nowrap")
				.css("left", "50%")
				.css("top", "2px").hide();
			
			if(layoutObj.isRound && layoutObj.isTable) {
				
				jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_ENCREASE')+"\"><span class=\"ui-icon ui-icon-plus\"></span></button>").appendTo($actions_div)
					.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, $obj.data("scheme").scheme+1); });
				jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_REDUCE')+"\"><span class=\"ui-icon ui-icon-minus\"></span></button>").appendTo($actions_div)
					.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, $obj.data("scheme").scheme-1); });
			}

			if(!layoutObj.isRound && layoutObj.isTable) {
				
				if(layoutObj._getTableResizers(true).length>0) {
					jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_REDUCE_V')+"\"><span class=\"ui-icon ui-icon-arrowstop-1-n\"></span></button>").appendTo($actions_div)
						.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, { width: $obj.data("scheme").scheme.width(), height: $obj.data("scheme").scheme.height()-1 }); });
					
					jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_ENCREASE_V')+"\"><span class=\"ui-icon ui-icon-arrowstop-1-s\"></span></button>").appendTo($actions_div)
						.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, { width: $obj.data("scheme").scheme.width(), height: $obj.data("scheme").scheme.height()+1 }); });
				}
				
				if(layoutObj._getTableResizers().length>0) {
					jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_REDUCE_H')+"\"><span class=\"ui-icon ui-icon-arrowstop-1-w\"></span></button>").appendTo($actions_div)
						.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, { width: $obj.data("scheme").scheme.width()-1, height: $obj.data("scheme").scheme.height()}); });
				
					jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_ENCREASE_H')+"\"><span class=\"ui-icon ui-icon-arrowstop-1-e\"></span></button>").appendTo($actions_div)
						.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._resizeObject($obj, { width: $obj.data("scheme").scheme.width()+1, height: $obj.data("scheme").scheme.height()}); });
				}
			}
			
			jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_EDIT')+"\"><span class=\"ui-icon ui-icon-pencil\"></span></button>").appendTo($actions_div)
				.click(function(event){  var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._editObject($obj);  });
			
			if(!layoutObj.isRound && layoutObj.isTable) {
				jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_ROTATE')+"\"><span class=\"ui-icon ui-icon-arrowrefresh-1-e\"></span></button>").appendTo($actions_div)
					.click(function(event){ var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._rotateObject($obj); });
			}
			
			jQuery("<button class=\"ui-state-default ui-corner-all\" title=\""+this._('ACTION_DELETE')+"\"><span class=\"ui-icon ui-icon-trash\"></span></button>").appendTo($actions_div)
				.click(function(event){ if(confirm(jQuery(".mp-canvas").data("mp-manager")._('ACTION_DELETE_CONFIRM'))) {var $obj = jQuery(this).closest(".mp-obj"); jQuery(".mp-canvas").data("mp-manager")._removeObject($obj);} });
	
			$area.append($actions_div);
			$actions_div
				.css("margin-left", -$actions_div.width()/2);
		},
	
	
		_editObject: function($obj_container) {
			var layoutObj = $obj_container.data("scheme");
			
			var $dialog = jQuery("<div title=\'"+this._('ACTION_EDIT')+"\'/>").addClass("mp-obj-dialog");
			var $tbl = jQuery("<table/>").appendTo($dialog);
			
			$tbl.append("<tr><td><label>"+this._('TITLE')+": </label></td><td><input type=\'text\' name=\'title\'/></td</tr>");
			
			if(layoutObj.isTable && layoutObj.isRound)
				$tbl.append("<tr><td><label>"+this._('PLACE_COUNT')+": </label></td><td><input type=\'number\' min=\'2\' name=\'places\'/></td></tr>");
			
			$dialog.find("input[name=title]").val(layoutObj.title);
			$dialog.find("input[name=places]").val(this._getTableSits($obj_container).length);
			
			$dialog.dialog({
				resizable: false,
				modal: true,
				buttons: {
					"Применить": function() {
						var manager = jQuery(".mp-canvas").data("mp-manager");
						layoutObj.title = jQuery(this).find("input[name=title]").val();
						var places = jQuery(this).find("input[name=places]").val();
						
						manager._setTablePlacesCount($obj_container, places);
						
						var data = manager._serializeObject($obj_container);
						manager._removeObject($obj_container);
						manager._processObject(manager.stage, data);
						
						jQuery( this ).dialog( "close" );
					},
					"Отмена": function() {
						jQuery( this ).dialog( "close" );
					}
				}
			});
			
		},
		
		_setTablePlacesCount: function($obj_container, count) {
			var layoutObj = $obj_container.data("scheme");
			
			if(layoutObj.isTable && layoutObj.isRound) {
				layoutObj.scheme = Math.max(count, 2);
			}			
			
			console.log(count);
		},
		
		_bringToFront: function($obj) {
			var $children = jQuery($obj).parent().children().get();
			var _max_zIndex = 0;
			var $_itm = null;
			
			jQuery.each($children, function(idx, itm){ _max_zIndex = Math.max(_max_zIndex, parseInt(jQuery(itm).css("z-index"))); });
			jQuery.each($children, function(idx, itm){ if(_max_zIndex == parseInt(jQuery(itm).css("z-index"))) $_itm=jQuery(itm); });
			
			if(!empty($_itm))
				$_itm.css("z-index", $obj.css("z-index"));
			$obj.css("z-index", _max_zIndex);
		},
	
		_rotateObject: function($obj_container) {
			
			var layoutObj = $obj_container.data("scheme");
			layoutObj.sits = this._getTableSits($obj_container);			
			
			layoutObj.rotateScheme();
			
			var data = this._serializeObject($obj_container);
			data.sits = layoutObj.sits; 
			
			this._removeObject($obj_container);
			this._processObject(this.stage, data);
		},
	
		_resizeObject: function($obj_container, size) {
			
			var layoutObj = $obj_container.data("scheme");
			
			layoutObj.resizeScheme(size);
			
			var data = this._serializeObject($obj_container);	
			
			this._removeObject($obj_container);
			this._processObject(this.stage, data);
		},
	
		_removeObject: function($obj_container) {
			$obj_container.find(".mp-draggable-guest").each(function(){
				jQuery(".mp-canvas").data("mp-manager")._revertGuest(".mp-droppable.mp-guests", {draggable: jQuery(this)});
			});
	
			$obj_container.draggable("destroy").resizable("destroy").remove();
		},
		
		_addPlaceHolder: function($obj_container, $trgt) {
			$trgt.addClass("mp-place-holder")
			.css("width", $obj_container.data("scheme").placeSize)
			.css("height", $obj_container.data("scheme").placeSize)
			.droppable({
				activeClass: "ui-custom-highlight",
				hoverClass: "ui-state-highlight",
				accept: ".mp-draggable-guest",
				drop: function( event, ui ) {
					jQuery(".mp-canvas").data("mp-manager")._takeSit(this, ui);
				}
			})
			//.hover(function(){jQuery(".mp-canvas").data("mp-manager")._bringToFront(jQuery(this));})
			;
		},
		
		_getTableSits: function ($obj_container) {
			var sits = []; 
			$obj_container.find(".mp-place-holder").each(function(){
				
				var $guest = jQuery(this).find(".mp-draggable-guest");
				
				if($guest.length) {
					$guest.data("data").position = jQuery(this).data("position");
					sits.push($guest.data("data"));
				} else
					sits.push(null);
			});
			return sits;
		},
		
		_renderSits: function ($obj_container) {
			var layoutObj = $obj_container.data("scheme");
			var sits = jQuery.extend([], $obj_container.data("scheme").sits);
			var $guests = jQuery(".mp-toolbar .mp-guests").find("li.mp-draggable-guest");
			
			for(var i=0; i<sits.length; i++) {
				var exists = false;
				for(var j=0; j<$guests.length; j++) {
					if(sits[i]!=null && jQuery($guests[j]).data("data").id == sits[i].id) {
						exists = true;
						jQuery($guests[j]).data("data").position = sits[i].position;
						sits[i] = jQuery($guests[j]); 
						break;
					}
				}
				
				if(!exists) {
					sits[i] = null;
				}
			}
			
			if(layoutObj.isTable && !layoutObj.isRound) {
				var grid = this._getTableGrid($obj_container);
				for(var i=0; i<sits.length; i++) {
					if(sits[i]!=null){						
						var _pos = sits[i].data("data").position;
						if(!empty(grid[_pos.y][_pos.x]))
							this._takeSit(grid[_pos.y][_pos.x].find(".mp-place-holder"), { draggable: sits[i] });
					}
				}
			} else {
				var i = 0;
				$obj_container.find(".mp-place-holder").each(function(){
					if(sits[i]!=null)
						jQuery(".mp-canvas").data("mp-manager")._takeSit(this, { draggable: sits[i] });
					i++;
				});
			}
		},
		
		_takeSit: function(placeholder, ui) {
			ui.draggable.appendTo(placeholder).css("left", 0).css("top", 0).css("position", "relative");
		},
		
		_revertGuest: function(trgt, ui) {
			ui.draggable.appendTo(jQuery(trgt).find("ul")).css("left", 0).css("top", 0).css("position", "relative");
			this._sortGuests();
		}
	};
	
//})(jQuery);